package org.rain.core.codegen.support;

import org.rain.core.codegen.IMetaService;
import org.rain.core.codegen.model.ColumnMeta;
import org.rain.core.codegen.model.TableMeta;

import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

/**
 * created by yangtong on 2025/4/6 下午12:11
 * <br/>
 * 获取数据库元数据
 */
public class DefaultConnectionMetaServiceImpl extends DefaultConnectionServiceImpl implements IMetaService {
    @Override
    public List<String> listCatalogs() throws SQLException {
        List<String> list = new ArrayList<>();
        Connection connection = null;
        ResultSet catalogs = null;
        try {
            connection = getConnection();
            DatabaseMetaData metaData = connection.getMetaData();
            catalogs = metaData.getCatalogs();
            while (catalogs.next()) {
                String catalogName = catalogs.getString("TABLE_CAT");
                list.add(catalogName);
            }
        } finally {
            closeResultSet(catalogs);
            closeConnection(connection);
        }
        return list;
    }

    /**
     * 会返回当前连接的数据库里面的schema
     */
    @Override
    public List<String> listSchemas(String catalog) throws SQLException {
        List<String> list = new ArrayList<>();
        Connection connection = null;
        ResultSet schemas = null;
        try {
            connection = getConnection();
            DatabaseMetaData metaData = connection.getMetaData();
            schemas = metaData.getSchemas();
            while (schemas.next()) {
                String schemaName = schemas.getString("TABLE_SCHEM");
                String catalogName = schemas.getString("TABLE_CATALOG");
                list.add(schemaName);
            }
        } finally {
            closeResultSet(schemas);
            closeConnection(connection);
        }
        return list;
    }

    @Override
    public List<TableMeta> listTables(String catalog, String schema, String table) throws SQLException {
        List<TableMeta> list = new ArrayList<>();
        Connection connection = null;
        ResultSet rs = null;
        try {
            connection = getConnection();
            catalog = connection.getCatalog();
            DatabaseMetaData metaData = connection.getMetaData();
            rs = metaData.getTables(catalog, schema, table, new String[]{"TABLE"});
            while (rs.next()) {
                TableMeta tableMeta = new TableMeta();
                //获取表名
                String tableName = rs.getString("TABLE_NAME");
                tableMeta.setTable(tableName);
                //表描述
                String remarks = rs.getString("REMARKS");
                tableMeta.setComment(remarks);
                tableMeta.setCatalog(catalog);
                tableMeta.setSchema(schema);

                //获取表主键
                List<String> keys = parsePrimaryKeys(metaData, catalog, schema, tableName);
                tableMeta.setPrimaryKeys(keys);
                list.add(tableMeta);
            }
        } finally {
            closeResultSet(rs);
            closeConnection(connection);
        }
        return list;
    }

    @Override
    public List<ColumnMeta> listColumns(String catalog, String schema, String tableName) throws SQLException {
        List<ColumnMeta> list = new ArrayList<>();
        Connection connection = null;
        ResultSet columns = null;
        try {
            connection = getConnection();
            catalog = connection.getCatalog();
            DatabaseMetaData metaData = connection.getMetaData();
            columns = metaData.getColumns(catalog, schema, tableName, null);
            while (columns.next()) {
                ColumnMeta columnMeta = new ColumnMeta();
                columnMeta.setCatalog(catalog);
                columnMeta.setSchema(schema);
                columnMeta.setTable(tableName);
                //列名
                String columnName = columns.getString("COLUMN_NAME");
                columnMeta.setColumnName(columnName);
                //字段类型
                String typeName = columns.getString("TYPE_NAME");
                columnMeta.setColumnType(typeName);
                //java类型
                String javaType = columns.getString("DATA_TYPE");
                columnMeta.setJavaType(javaType);
                //是否自增
                boolean isAutoincrement = columns.getBoolean("IS_AUTOINCREMENT");
                columnMeta.setAutoIncrement(isAutoincrement);
                //字段长度
                int columnSize = columns.getInt("COLUMN_SIZE");
                columnMeta.setColumnLength(columnSize);
                //小数点位数
                int decimalDigits = columns.getInt("DECIMAL_DIGITS");
                columnMeta.setDecimalDigits(decimalDigits);
                //字段是否允许为空
                boolean isNullable = (columns.getInt("NULLABLE") == DatabaseMetaData.columnNullable);
                columnMeta.setNullable(isNullable);
                //字段备注
                String columnComment = columns.getString("REMARKS");
                columnMeta.setColumnComment(columnComment);
                //默认值
                String defaultValue = columns.getString("COLUMN_DEF");
                columnMeta.setDefaultValue(defaultValue);

                list.add(columnMeta);
            }
        } finally {
            closeResultSet(columns);
            closeConnection(connection);
        }

        return list;
    }

    @Override
    public List<String> listPrimaryKeys(String catalog, String schema, String tableName) throws SQLException {
        List<String> list;
        Connection connection = null;
        try {
            connection = getConnection();
            catalog = connection.getCatalog();
            DatabaseMetaData metaData = connection.getMetaData();
            list = parsePrimaryKeys(metaData, catalog, schema, tableName);

        } finally {
            closeConnection(connection);
        }
        return list;
    }

    @Override
    public ColumnMeta getColumnDetail(String catalog, String schema, String tableName, String columnName) {
        return null;
    }

    private List<String> parsePrimaryKeys(DatabaseMetaData metaData, String catalogsName, String schema, String tableName) throws SQLException {
        List<String> keys = new ArrayList<>();
        ResultSet primaryKeys = null;
        try {
            primaryKeys = metaData.getPrimaryKeys(catalogsName, schema, tableName);

            while (primaryKeys.next()) {
                String keyName = primaryKeys.getString("COLUMN_NAME");
                keys.add(keyName);
            }
        } finally {
            closeResultSet(primaryKeys);
        }
        return keys;
    }
}
